/*!
	\file LecteurPhraseAvecArbre.h
	\brief La spécification de la classe LecteurPhraseAvecArbre

	Décrit la liste des méthodes et attributs associés à la class LecteurPhraseAvecArbre
	\author Arnaud MAILLET
	\date 03.01.2009
*/

/*! 
	\class LecteurPhraseAvecArbre
	\brief La classe construit l'arbre associé au fichier interprété

	Cette classe permet de représenter sous la forme d'un arbre le fichier interprété
	Les méthodes suivantes sont associées à un objet de type LecteurPhraseAvecArbre :
	\li analyse
	\li getTs
	\li getArbre
	\li programme
	\li seqInst
	\li inst
	\li instSi
	\li instTq
	\li instRepeter
	\li instPour
	\li instLire
	\li instEcrire
	\li instChoisir
	\li instCas
	\li affectation
	\li expression
	\li terme
	\li expEt
	\li expOu
	\li relation
	\li facteur
	\li opAdd
	\li opMult
	\li opUnaire
	\li opEt
	\li opOu
	\li opRel
	\li testerSymCour
	\li sauterSymCour
	\li erreur
*/
#ifndef LECTEURPHRASEAVECARBRE_H_
#define LECTEURPHRASEAVECARBRE_H_

#include "Symbole.h"
#include "LecteurSymbole.h"
#include "TableSymboles.h"
#include "Arbre.h"

#include <string>
using namespace std;

class LecteurPhraseAvecArbre
{
public:
	/*! 
	\fn LecteurPhraseAvecArbre(string nomFich)
	\brief Constructeur de la classe LecteurPhraseAvecArbre.

	Ce constructeur construit un lecteur de phrase pour interpreter le programme dans le fichier nomFich
	\param nomFich - le nom du fichier
        */
	LecteurPhraseAvecArbre(string nomFich);	

	/*! 
	\fn void analyse()
	\brief Permet d'analyser le fichier à interpreter

	Si le contenu du fichier est conforme à la grammaire, cette méthode se termine normalement et affiche un message "Syntaxe correcte". La table des symboles (ts) et l'arbre abstrait (arbre) auront été construits. Sinon, le programme sera interrompu en levant une exception de type Erreur.
        */
	void analyse();

	/*! 
	\fn inline TableSymbole getTs()
	\brief Retourne la table des symboles du fichier interprété
	\return la table des symboles du fichier interprété
	*/
	inline TableSymboles getTs() { return ts; }

	/*! 
	\fn inline Noeud* getArbre()
	\brief Retourne l'arbre du fichier interprété
	\return  Retourne l'arbre du fichier interprété
	*/
	inline Noeud* getArbre() { return arbre; }
	

private:
	/*!
	\var LecteurSymbole ls
	\brief  Contient le lecteur de symboles utilisé pour analyser le fichier
	*/
	LecteurSymbole ls;

	/*!
	\var TableSymboles ts
	\brief  Contient la table des symboles valués
	*/
	TableSymboles ts;

	/*!
	\var Noeud* arbre
	\brief  Contient l'arbre abstrait
	*/
	Noeud* arbre;

	
	/*! 
	\fn Noeud* programme()
	\brief <programme> ::= debut <seqInst> fin FIN_FICHIER
	\return le noeud du début du programme interprété
	*/
	Noeud*  programme();

	/*! 
	\fn Noeud* seqInst()
	\brief <seqInst> ::= <inst> ; { <inst> ; }
	\return le noeud du début d'une séquence d'instruction
	*/
	Noeud*  seqInst();

	/*! 
	\fn Noeud* inst()
	\brief <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter> | <instPour> | <instLire> | <instEcrire> | <instChoisir>
	\return le noeud du début d'une instruction
	*/
	Noeud*  inst();

	/*! 
	\fn Noeud* instSi()
	\brief <instSi> ::= si ( <expEt> ) <seqInst> { sinonsi ( <expEt> ) <seqInst> } [ sinon <seqInst> ] finsi
	\return le noeud du début d'une instruction Si
	*/
	Noeud*  instSi();

	/*! 
	\fn Noeud* instTq()
	\brief <instTq> ::= tantque ( <expEt> ) <seqInst> fintantque
	\return le noeud du début d'une instruction Tantque
	*/
	Noeud*  instTq();

	/*! 
	\fn Noeud* instRepeter()
	\brief <instRepeter> ::= repeter <seqInst> jusqua ( <expEt> )
	\return le noeud du début d'une instruction Repeter
	*/
    	Noeud*  instRepeter();

	/*! 
	\fn Noeud* instPour()
	\brief <instPour> ::= pour (<affectation> ; <expEt> ; <affectation> ) <seqInst> finpour
	\return le noeud du début d'une instruction Pour
	*/
	Noeud*  instPour();

	/*! 
	\fn Noeud* instLire()
	\brief <instLire> ::= lire ( <variable> )
	\return le noeud du début d'une instruction Lire
	*/
	Noeud*  instLire();

	/*! 
	\fn Noeud* instEcrire()
	\brief <instEcrire> ::= ecrire ( <expression> | <chaine> )
	\return le noeud du début d'une instruction Ecrire
	*/
	Noeud*  instEcrire();

	/*! 
	\fn Noeud* instChoisir()
	\brief <instChoisir> := choisir (<variable>) { instCas } finchoisir
	\return le noeud du début d'une instruction Choisir
	*/
	Noeud*  instChoisir();
	
	/*! 
	\fn Noeud* instCas()
	\brief <instCas> := cas <variable> | <entier> : <seqInst> (defaut : <seqInst>)
	\return le noeud du début d'une instruction Cas
	*/	
	Noeud*  instCas();

	/*! 
	\fn Noeud* affectation()
	\brief <affectation> ::= <variable> = <expression>
	\return le noeud du début d'une affectation
	*/	
	Noeud*  affectation();

	/*! 
	\fn Noeud* expression()
	\brief <expression> ::= <terme> { <opAdd> <terme> }
	\return le noeud du début d'une expression
	*/		
	Noeud*  expression();

	/*! 
	\fn Noeud* terme()
	\brief <terme> ::= <facteur> { <opMult> <facteur> }
	\return le noeud du début d'un terme
	*/	
	Noeud*  terme();
	
	/*! 
	\fn Noeud* expEt()
	\brief <expEt> ::= <expOu> { <opEt> <expOu> }
	\return le noeud du début d'un expEt
	*/	
	Noeud*  expEt();

	/*! 
	\fn Noeud* expOu()
	\brief <expOu> ::= <relation> { <opOu> <relation> }
	\return le noeud du début d'un expOu
	*/	
	Noeud*  expOu();

	/*! 
	\fn Noeud* relation()
	\brief <relation> ::= <expression> { <opRel> <expression> }
	\return le noeud du début d'une relation
	*/	
	Noeud*  relation();

	/*! 
	\fn Noeud* facteur()
	\brief <facteur> ::= <entier> | <chaine> | <variable> | <opUnaire> <expEt> | ( <expEt> )
	\return le noeud du début d'un facteur
	*/
	Noeud* facteur();

	/*! 
	\fn Symbole opAdd()
	\brief <opAdd> ::= + | -
	\return le symbole d'une opAdd
	*/
	Symbole opAdd();

	/*! 
	\fn Symbole opMult()
	\brief <opMult> ::= * | /
	\return le symbole d'une opMult
	*/
	Symbole opMult();

	/*! 
	\fn Symbole opUnaire()
	\brief <opUnaire> ::= non | -
	\return le symbole d'une opUnaire
	*/
	Symbole opUnaire();

	/*! 
	\fn Symbole opEt()
	\brief <opEt> ::= et
	\return le symbole d'une opEt
	*/
	Symbole opEt();

	/*! 
	\fn Symbole opOu()
	\brief <opOu> ::= ou
	\return le symbole d'une opOu
	*/
	Symbole opOu();

	/*! 
	\fn Symbole opRel()
	\brief <opRel> ::= == | != | < | <= | > | >=
	\return le symbole d'une opRel
	*/
	Symbole opRel();

	/*! 
	\fn void testerSymCour (string ch)
	\brief Permet de tester le symbole courant

	Si symbole courant != ch, erreur : on leve une exception, sinon rien
	\param ch - la chaine à tester avec le symbole courant
        */
	void testerSymCour (string ch);

	/*! 
	\fn void sauterSymCour (string ch)
	\brief Permet de sauter le symbole courant

	Si symbole courant == ch, on passe au symbole suivant, sinon on leve une exception : on arrete
	\param ch - la chaine à tester avec le symbole courant
        */
	void sauterSymCour (string ch);

	/*! 
	\fn void erreur (string mess)
	\brief Permet de lever une erreur avec le message voulu

	Leve une erreur avec le message voulu
	\param mess - le message à afficher dans l'erreur
        */	
	void erreur (string mess);
};

#endif /* LECTEURPHRASEAVECARBRE_H_ */
